一般傳統會用session來做登入狀態的驗證,客端的cookie有對應的session key,每次request後端都會拿session key,去驗證session的資訊,有沒有登入之類。JTW Token也在做類似的事情,差在那些資料就記在Token的本身,等於說可以不需要在全何地方去記錄這些登入資訊,你拿著Token的可以了。
現在很多後端的伺服器不只有一台,如果session的資料只記在某一台的記憶體上,那其他台會找不到session,用token就沒有這問題。當然把session存在redis一樣可以解決這問題,但你還是要多存這些資料,以這系列來說會員資料就只有user_id & user_name,所以用JWT Token會最方便。
首先來產生一組secret key
你可以亂打一些字串或者用下面這個網站產生一組超長的密碼
https://www.grc.com/passwords.htm
加個config
confit.yaml
JWT_TOKEN_LIFE: 2592000 // token的存活時間 30天
JWT_SECRET: "YOUR_SECRET" // 加密用的
pkg/jwt/jwt.go
// Key cookie key
const Key = "token"
// Claims Token的結構,裡面放你要的資訊
type Claims struct {
Username string `json:"user_name"`
UserID string `json:"user_id"`
jwt.StandardClaims
}
// GenerateToken 產生Token
func GenerateToken(userID, username string) (string, error) {
nowTime := time.Now()
expireTime := nowTime.Add(time.Duration(config.Val.JWTTokenLife) * time.Second) // Token有效時間
claims := Claims{
username,
userID,
jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
Issuer: "tomato",
},
}
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, err := tokenClaims.SignedString([]byte(config.Val.JWTSecret))
return token, err
}
// ParseToken 驗證Token對不對,如果對就回傳user info
func ParseToken(token string) (userID, userName string, err error) {
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(config.Val.JWTSecret), nil
})
if err != nil {
return "", "", err
}
claims, ok := tokenClaims.Claims.(*Claims)
if !ok || !tokenClaims.Valid {
return "", "", errors.New("tokenClaims invalid")
}
return claims.UserID, claims.Username, nil
}
在登入的地方補上這一段就完成了
// create jwt token
jwtToken, err := jwt.GenerateToken(id, name)
if err != nil {
c.Redirect(http.StatusFound, "/")
return
}
// 測試domain先寫localhost secure先寫false
c.SetCookie(jwt.Key, jwtToken, config.Val.JWTTokenLife, "/", "localhost", false, true)
重跑一次登入流程,就會多了一個token在cookie那裡哦~
今天的commit
今天先到這!謝謝大家~~